﻿#include "framework.h"
#include "ChatWindow.h"
#include "Const.h"
#include "Resource.h"

// 变量声明
extern TCHAR gUsername[USERNAME_BUF_LEN];  // 用户名

// 函数声明
static void ChatWindow_Delete(ChatWindow*);
static void ChatWindow_OnButtonSendClicked(ChatWindow*);
static void ChatWindow_OnShowWindow(ChatWindow*, BOOL);
static INT_PTR CALLBACK ChatWindow_Proc(HWND, UINT, WPARAM, LPARAM);
static void ChatWindow_SetContent(ChatWindow*, const ChatInfo*);

/**
 * 创建聊天窗口。
 * @param callback      回调
 * @param friendName    好友名
 * @return 聊天窗口
 */
ChatWindow* New_ChatWindow(HWND callback, LPCTSTR friendName) {
    ChatWindow* chatWindow = (ChatWindow*)calloc(1, sizeof(ChatWindow));

    // 初始化数据
    chatWindow->mCallback = callback;
    chatWindow->mHandle = CreateDialog(NULL, MAKEINTRESOURCE(IDD_CHAT_WINDOW), callback, ChatWindow_Proc);
    SetWindowLongPtr(chatWindow->mHandle, GWLP_USERDATA, (LONG_PTR)chatWindow);
    SendMessage(GetDlgItem(chatWindow->mHandle, IDC_EDIT_INPUT), EM_SETLIMITTEXT, MAX_CONTENT_LEN, 0);

    // 初始化函数
    chatWindow->deleteSelf = ChatWindow_Delete;
    chatWindow->setContent = ChatWindow_SetContent;

    // 设置窗口标题
    _tcscpy_s(chatWindow->mFriendName, USERNAME_BUF_LEN, friendName);
    SetWindowText(chatWindow->mHandle, chatWindow->mFriendName);

    return chatWindow;
}

/**
 * 删除聊天窗口。
 * @param chatWindow    聊天窗口
 */
static void ChatWindow_Delete(ChatWindow* chatWindow) {
    DestroyWindow(chatWindow->mHandle);
    free(chatWindow);
}

/**
 * "发送"按钮的单击响应方法。
 * @param chatWindow    聊天窗口
 */
static void ChatWindow_OnButtonSendClicked(ChatWindow* chatWindow) {
    ChatInfo* chatInfo = NULL;
    HWND editInput = GetDlgItem(chatWindow->mHandle, IDC_EDIT_INPUT);
    int contentLength = GetWindowTextLength(editInput) +
        (int)_tcslen(LEFT_BR) + (int)_tcslen(RIGHT_BR) + (int)_tcslen(WRAP) + 1;
    TCHAR* content = NULL;
    SYSTEMTIME systemTime = { 0 };
    TCHAR time[DATE_TIME_BUF_LEN] = { 0 };

    // 获取用户输入的聊天内容
    content = (TCHAR*)calloc(1, contentLength * sizeof(TCHAR));
    GetWindowText(editInput, content, contentLength);

    // 获取当前时间
    GetLocalTime(&systemTime);
    _stprintf_s(time, DATE_TIME_BUF_LEN, DATE_TIME_FORMAT, systemTime.wYear,
        systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond);

    // 显示聊天内容
    chatInfo = New_ChatInfo(content, chatWindow->mFriendName, gUsername, time);
    ChatWindow_SetContent(chatWindow, chatInfo);

    // 清空聊天内容编辑框
    SetWindowText(editInput, _T(""));

    // 发送聊天内容
    SendMessage(chatWindow->mCallback, UM_CHAT_C2S, (WPARAM)chatInfo, 0);
    SetFocus(editInput);

    free(chatInfo);
    free(content);
}

/**
 * 窗口显示事件的响应方法。
 * @param chatWindow    聊天窗口
 * @param show          显示窗口则为 TRUE，隐藏窗口则为 FALSE
 */
static void ChatWindow_OnShowWindow(ChatWindow* chatWindow, BOOL show) {
    HWND editInput = NULL;
    if (show) {
        editInput = GetDlgItem(chatWindow->mHandle, IDC_EDIT_INPUT);
        SetFocus(editInput);
    }
}

/**
 * 窗口过程函数。
 * @param window    窗口
 * @param message   事件标识
 * @param wParam    事件相关信息
 * @param lParam    事件相关信息
 * @return 事件在此被处理则返回 TRUE，否则返回 FALSE
 */
static INT_PTR CALLBACK ChatWindow_Proc(HWND window, UINT message, WPARAM wParam, LPARAM lParam) {
    ChatWindow* chatWindow = (ChatWindow*)GetWindowLongPtr(window, GWLP_USERDATA);
    WORD id = LOWORD(wParam);
    UNREFERENCED_PARAMETER(lParam);

    switch (message) {
        case WM_COMMAND:
            if (id == IDC_BUTTON_SEND) {
                ChatWindow_OnButtonSendClicked(chatWindow);
                return TRUE;
            }
            if (id == IDOK || id == IDCANCEL) {
                EndDialog(window, id);
                return TRUE;
            }
            break;
        case WM_SHOWWINDOW:
            ChatWindow_OnShowWindow(chatWindow, (BOOL)wParam);
            return TRUE;
    }
    return FALSE;
}

/**
 * 设置聊天内容。
 * @param chatWindow    聊天窗口
 * @param chatInfo      聊天信息
 */
static void ChatWindow_SetContent(ChatWindow* chatWindow, const ChatInfo* chatInfo) {
    HWND editHistory = GetDlgItem(chatWindow->mHandle, IDC_EDIT_HISTORY);
    int textLen = GetWindowTextLength(editHistory);
    TCHAR* content = NULL;
    int lines = 0;

    // 计算聊天内容长度
    textLen += (int)_tcslen(chatInfo->mSrcUsername);
    textLen += (int)_tcslen(chatInfo->mTime);
    textLen += (int)_tcslen(chatInfo->mContent);
    textLen += (int)(_tcslen(LEFT_BR) + _tcslen(RIGHT_BR) + _tcslen(WRAP) + 1);
    content = (TCHAR*)calloc(1, textLen * sizeof(TCHAR));

    // 生成聊天内容
    GetWindowText(editHistory, content, textLen);
    _tcscat_s(content, textLen, chatInfo->mSrcUsername);
    _tcscat_s(content, textLen, LEFT_BR);
    _tcscat_s(content, textLen, chatInfo->mTime);
    _tcscat_s(content, textLen, RIGHT_BR);
    _tcscat_s(content, textLen, chatInfo->mContent);
    _tcscat_s(content, textLen, WRAP);

    // 显示聊天内容
    SetWindowText(editHistory, content);
    free(content);

    // 滚动到最底行
    lines = (int)SendMessage(editHistory, EM_GETLINECOUNT, 0, 0);
    SendMessage(editHistory, EM_LINESCROLL, 0, lines);
}
